<?php
class App_Source_Tags_Mapper extends Mozg_Mapper_Data
{
	private $_source;

	public function __construct()
	{
		$this->_source = Mozg_Source::get('default');
	}

	public function Save($area, $id, $tags = array())
	{
		$area = $this->_source->quote((string)$area);
		$id = (int)$id;
		$tags = $this->GetFilteredArr($tags);

		$this->_source->exec("DELETE
									FROM
										%%tag%%
					            	WHERE
					            		area = " .$area. " AND
					            		id = " .$id );
		$sql = '';
		foreach ($tags as $tag)
		{
			$sql .= '(' .$area. ', ' .$id. ', ' .$this->_source->quote($tag). '),';
		}

		$num = 0;

		$sql = rtrim($sql, ',');
		if (strlen($sql))
		{
			$num = $this->_source->exec("insert ignore into %%tag%%(area, id, tag)
				            values
				            " .$sql);
		}

		return $num;
	}

	public function CheckName($name)
	{
		return Mozg::Lib('str')->Len($name) >= 1;
	}

	public function GetSearchStr($tags = array())
	{
		$tags = $this->GetSearchArr($tags);

		$str = ',';
		foreach ($tags as $tag)
		{
			$str .= $tag. ',';
		}

		return $str;
	}

	public function GetSearchArr($tags = array())
	{
		$tags = $this->GetFilteredArr($tags);
		foreach ($tags as &$tag)
		{
			//дополняем tag до 4-х символов нулями,
			//потому что полнотекстовый поиск работает со словами не короче 4-х символов
			$tag = str_replace(array(' ', '-'), '_', Mozg::Lib('Str')->Pad($tag, 4, '0', STR_PAD_LEFT));
		}

		return $tags;
	}

	public function GetFilteredArr($tags = array())
	{
		if (!is_array($tags))
		{
			$tags = explode(',', $tags);
		}

		return array_filter(array_unique(array_map('trim', $tags)), array($this, 'CheckName'));
	}

	private function GetSqlFromFilter($filter = null)
	{
		$sqlFilter = array('where' => array(), 'join' => array());
		if (!($filter instanceof Mozg_Property_Params)) $filter = $this->GetFilter($filter);

		if (strlen($filter->GetArea()))
		{
			$sqlFilter['where'][] = 'area = ' .$this->_source->quote($filter->GetArea());
		}

		if (strlen($filter->GetTag()))
		{
			$sqlTag = str_replace('%', '\%', $filter->GetTag()). '%';
			$sqlFilter['where'][] = 'tag LIKE ' .$this->_source->quote($sqlTag);
		}

		$sqlFilter['where'] = sizeof($sqlFilter['where']) ? '(' .implode(') and (', $sqlFilter['where']). ')' : '';
		$sqlFilter['join'] = sizeof($sqlFilter['join']) ?  implode(' ', $sqlFilter['join']) : '';

		return $sqlFilter;
	}

    protected function Find($filter = null, Mozg_Paginator $paginator = null)
    {
    	$sqlFilter = $this->GetSqlFromFilter($filter);

        $stmt = $this->_source->query("SELECT
													tag,
													count(id) `count`
							                     FROM
							                     	%%tag%%
							                     " .($sqlFilter['where'] ? " WHERE ". $sqlFilter['where'] : ""). "
							                     GROUP by tag
							                     ORDER BY tag
							                     " .($paginator ? "LIMIT " .$paginator->GetSqlLimit() : ""));
		$stmt->setFetchMode(PDO::FETCH_ASSOC);
        return $stmt->fetchAll();
    }

	public function GetList($filter = null, Mozg_Paginator $paginator = null)
	{
		return $this->Find($filter, $paginator);
	}

	public function GetOne($filter = null)
	{
		return current($this->Find($filter, new Mozg_Paginator(1,1)));
	}
}